#version 450 core

layout(binding = 0) uniform sampler2D diffuseTex;

layout(std140, binding = 0) uniform PerDraw
{
    mat4 viewMatrix;
    mat4 projMatrix;
    vec3 cameraPos;
};
layout(std140, binding = 1) uniform PointLight
{
    vec3 position;
    float range;
    vec3 color;
} pointLight;
layout(std140, binding = 2) uniform Material
{
    vec3 specColor;
    float specStrength;
};

uniform bool PHONG;

in Varyings
{
    vec3 positionWS;
    vec3 normalWS;
    vec2 uv;
} i;

out vec4 fragColor;

// 计算光照方程(Blinn-Phong)
vec3 Lighting(vec3 P, vec3 N, vec3 L, vec3 V, vec3 C)
{
    // 计算漫反射分量
    vec3 diffuse = max(0.0, dot(N, L)) * texture(diffuseTex, i.uv).rgb * C;
    // 计算高光分量（与phong模型不同，blinn-Phong用的是Half Vector，可以避免R与V点乘小于0的情况)
    // （这种情况下，Phong模型的高光分量为0，但实际情况下，高光应该是能看到的，并且向另一边延展）
    vec3 specular;
    if(PHONG)
    {
        vec3 R = reflect(-L, N);
        specular = C * specColor * pow(max(0.0, dot(V, R)), specStrength);
    }
    else
    {
        vec3 H = normalize(L + V);
        specular = C * specColor * pow(max(0.0, dot(N, H)), specStrength);
    }

    return diffuse + specular;
}

void main()
{
    vec3 P = i.positionWS;
    vec3 N = normalize(i.normalWS);
    vec3 L = normalize(pointLight.position - P);
    vec3 V = normalize(cameraPos - P);

    vec3 color = Lighting(P, N, L, V, pointLight.color);
    float dis2 = dot(pointLight.position - P, pointLight.position - P);
    float decay = 1.0 / (1.0 + 0.02 * dis2);
    float fac = step(dis2, pointLight.range * pointLight.range);
    fragColor = vec4(color * decay * fac, 1.0);

    // 应用gamma矫正
    float gamma = 2.2;
    fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / gamma));
}
